package io.mft.flow.core.executable.drive.impl;

import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import io.mft.commons.exception.MFTException;
import io.mft.commons.function.ExecuteReturn;
import io.mft.commons.function.RequestValue;
import io.mft.flow.core.executable.ChainCondition;
import io.mft.flow.core.executable.drive.ChainConditionDriver;
import io.mft.flow.core.executable.drive.ConditionDriveSourceProvider;
import io.mft.flow.core.executable.drive.ConditionDriverType;
import io.mft.flow.core.executable.drive.ConditionDriveSourceProvider.ProvideResult;
import io.mft.flow.data.ChainContext;
import io.mft.flow.data.ExecutableRequest;
import io.mft.flow.data.ExecutableResponse;
/**
 * 结果集迭代驱动，即前驱节点执行完成时将结果集的每条记录作为参数循环触发后继节点执行
 * @说明：TODO
 * @类型名称：IterateLoopSyncReturnChainConditionDriver
 * @创建者: 胡常建  
 * @创建时间: 2021年3月4日 上午8:48:21
 * @修改者: 胡常建  
 * @修改时间: 2021年3月4日 上午8:48:21
 */
public class IterateLoopSyncReturnChainConditionDriver extends ChainConditionDriver {

	Logger logger = LoggerFactory.getLogger(getClass());

	
	private RequestValue objectToRequestValue(Object data) {
		Map<?, ?> map=null;
		if (data instanceof Map<?, ?>) {
			map = (Map<?, ?>) data;
		}else {
			map=BeanUtil.beanToMap(data, false, true);
		}
		RequestValue kvMap=new RequestValue();
		map.entrySet().forEach(entry->{
			kvMap.set(String.valueOf(entry.getKey()),entry.getValue());
		});
		return kvMap;
	}
	@Override
	public ExecuteReturn drive(ChainContext context,ConditionDriveSourceProvider conditionDriveSourceProvider) throws Exception {
		ChainCondition currentChainCondition=chainCondition();
		ChainCondition nextChainCondition=currentChainCondition.getNextChainCondition();
		if (currentChainCondition.getCondition().conditionType().isSyncReturn()) {// 当前节点是同步节点则最后一个执行器的响应作为下一节点的入参
			dispatch(context,conditionDriveSourceProvider, new DispatchProcessor() {

				@Override
				public void process(Object data) throws Exception {
					RequestValue requestValue=new RequestValue();
					requestValue.initValue(context.getRequest().getRequestValue());
					requestValue.initValue(objectToRequestValue(data));
					ExecutableRequest request=new ExecutableRequest(requestValue);
					ExecutableResponse response = new ExecutableResponse();
					logger.debug("编排Chain:{}->>>当前逻辑单元类型:{},id:{}->>>迭代异步驱动执行逻辑单元类型:{},id:{},驱动参数:{}",context.getChainName(),currentChainCondition.getType().name(),currentChainCondition.getId(),nextChainCondition.getType().name(),nextChainCondition.getId(),request);
					executeNextChainCondition(context, nextChainCondition, request, response);
					convertResponseToContext(response, context);
				}
			});
		} else {
			RequestValue requestValue=new RequestValue();
			requestValue.initValue(context.getRequest().getRequestValue());
			ExecutableRequest request=new ExecutableRequest(requestValue);
			logger.debug("编排Chain:{}->>>当前逻辑单元类型:{},id:{}->>>异步驱动执行逻辑单元类型:{},id:{},驱动参数:{}",context.getChainName(),currentChainCondition.getType().name(),currentChainCondition.getId(),nextChainCondition.getType().name(),nextChainCondition.getId(),request);
			ExecutableResponse response = new ExecutableResponse();
			executeNextChainCondition(context, nextChainCondition, request, response);
			convertResponseToContext(response, context);
		}
		ExecuteReturn executeReturn=ExecuteReturn.builder().build();
		return executeReturn;
	}

	
	private void convertResponseToContext(ExecutableResponse response,ChainContext context) {
		response.getDsName().forEach(ds->{
			switch (ds.getType()) {
			case page:
				context.getResponse().resultObject(ds.getAliasName(),response.pageTObject(ds.getName()));
				break;
			case list:
				context.getResponse().resultObject(ds.getAliasName(),response.listObject(ds.getName()));
				break;
			case map:
				Object obj=response.dataObject(ds.getName());
				context.getResponse().resultObject(ds.getAliasName(), obj);
				break;
			default:
				break;
			}
		});
	}
	protected interface DispatchProcessor {
		public void process(Object data) throws Exception;
	}

	protected void dispatch(ChainContext context,ConditionDriveSourceProvider conditionDriveSourceProvider, DispatchProcessor processor)
			throws Exception {// 当前节点是同步节点则最后一个执行器的响应作为下一节点的入参
		ProvideResult provideResult=conditionDriveSourceProvider.provide(context);
		if (provideResult.getCode()!=0) {
			return;
		}
		if (ObjectUtil.isNull(provideResult.getList())) {
			throw new MFTException("不允许分发结果集为Null空");
		}
		List<Object> list=provideResult.getList();
		list.forEach(data -> {
			try {
				processor.process(data);
			} catch (Exception e) {
				throw new MFTException(e);
			}
		});
	}

	@Override
	public ConditionDriverType conditionDriverType() {
		return ConditionDriverType.iterateLoopSyncReturn;
	}
}
